package cool.webstudy.admin.service.impl.scheduler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import cool.webstudy.admin.constant.enums.CompetitionStatusEnum;
import cool.webstudy.admin.model.dto.competition.QueryCompetitionDetailInfoDTO;
import cool.webstudy.admin.model.dto.competition.team.QueryCompTeamDetailInfoDTO;
import cool.webstudy.admin.model.dto.scheduler.CompetitionStartSchedulerTaskDTO;
import cool.webstudy.admin.model.dto.scheduler.CreateSchedulerTaskDTO;
import cool.webstudy.admin.model.dto.scheduler.UpdateSchedulerTaskDTO;
import cool.webstudy.admin.service.*;
import cool.webstudy.admin.service.docker.ContainerService;
import cool.webstudy.common.constant.enums.EnabledStatusFlagEnum;
import cool.webstudy.common.utils.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 莫振双
 * @date 2025/3/5 20:04
 * @description: 赛题启动定时任务
 */
@Component("CompetitionStartSchedulerTask")
public class CompetitionStartSchedulerTask {
    private static final Logger logger = LoggerFactory.getLogger(CompetitionStartSchedulerTask.class);
    //声明全局序列化对象
    private final ObjectMapper objectMapper = new ObjectMapper();
    //声明全局变量，用于记录赛事回合次数
    private Map<String, Integer> competitionRoughInfoMap = new ConcurrentHashMap<>();
    @Autowired
    private CompetitionService competitionService;
    @Autowired
    private CompetitionTeamService competitionTeamService;
    @Autowired
    private ContainerService containerService;
    @Autowired
    private ISchedulerTaskService schedulerTaskService;
    @Autowired
    private DynamicFlagService dynamicFlagService;

    // 启动赛事进入加固阶段定时任务
    public void startCompetitionPreparingTask(String param) throws JsonProcessingException {
        if (StringUtils.isBlank(param)) {
            return;
        }
        //反序列化参数
        CompetitionStartSchedulerTaskDTO taskDTO = objectMapper.readValue(param, CompetitionStartSchedulerTaskDTO.class);
        //将赛事状态改为加固阶段
        competitionService.updateCompetitionStatus(taskDTO.getCompetitionUnCode(), CompetitionStatusEnum.PREPARING);
        //将开始赛题定时任务修改成一个5分钟后开始比赛的定时任务
        UpdateSchedulerTaskDTO updateSchedulerTaskDTO = new UpdateSchedulerTaskDTO();
        updateSchedulerTaskDTO.setUnCode(taskDTO.getCompetitionUnCode());
        updateSchedulerTaskDTO.setBeanName("CompetitionStartSchedulerTask");
        updateSchedulerTaskDTO.setMethodName("startCompetitionStartTask");
        updateSchedulerTaskDTO.setMethodParams(param);
        updateSchedulerTaskDTO.setTaskStatus(EnabledStatusFlagEnum.ENABLED);
        updateSchedulerTaskDTO.setCronExpression("0 0/1 * * * ?");
        updateSchedulerTaskDTO.setRemark("赛事开始加固阶段定时任务");
        schedulerTaskService.updateSchedulerTask(updateSchedulerTaskDTO);
    }

    public void startCompetitionStartTask(String param) throws JsonProcessingException {
        if (StringUtils.isBlank(param)) {
            return;
        }
        //反序列化参数
        CompetitionStartSchedulerTaskDTO taskDTO = objectMapper.readValue(param, CompetitionStartSchedulerTaskDTO.class);
        //查询赛事信息
        QueryCompetitionDetailInfoDTO queryCompetitionDetailInfo = competitionService.queryCompetitionDetailInfo(taskDTO.getCompetitionUnCode());
        if (Objects.isNull(queryCompetitionDetailInfo.getUnCode())) {
            logger.error("赛事不存在,赛事业务主键：{}", taskDTO.getCompetitionUnCode());
            return;
        }
        taskDTO.setRoundCount(queryCompetitionDetailInfo.getRoundCount());
        //将赛事状态修改为开始状态
        competitionService.updateCompetitionStatus(taskDTO.getCompetitionUnCode(), CompetitionStatusEnum.IN_THE_COMP);
        taskDTO.setUnCode(taskDTO.getCompetitionUnCode());
        //如果总回合数大于等于1则立即执行一次赛刷新flag逻辑
        if (queryCompetitionDetailInfo.getRoundCount() >= 1) {
            //如果赛事回合次数不存在，则初始化赛事回合次数为1，使用computeIfAbsent方法，保证原子性
            competitionRoughInfoMap.computeIfAbsent(taskDTO.getUnCode(), k -> 1);
            //更新flag
            dynamicFlagService.batchRefreshFlag(taskDTO.getCompetitionUnCode());
            //更新赛事回合次数
            competitionService.updateCompetitionCurrentRoundCount(taskDTO.getUnCode());
         }
        //计算cron表达式
        String cronExpression = "0 0/" + queryCompetitionDetailInfo.getRoundDuration() + " * * * ?";
        UpdateSchedulerTaskDTO updateSchedulerTaskDTO = new UpdateSchedulerTaskDTO();
        updateSchedulerTaskDTO.setUnCode(taskDTO.getUnCode());
        updateSchedulerTaskDTO.setBeanName("CompetitionStartSchedulerTask");
        updateSchedulerTaskDTO.setMethodName("startCompetitionCircularTask");
        updateSchedulerTaskDTO.setMethodParams(objectMapper.writeValueAsString(taskDTO));
        updateSchedulerTaskDTO.setCronExpression(cronExpression);
        updateSchedulerTaskDTO.setTaskStatus(EnabledStatusFlagEnum.ENABLED);
        updateSchedulerTaskDTO.setRemark("赛事开始循环定时任务");
        schedulerTaskService.updateSchedulerTask(updateSchedulerTaskDTO);
    }

    // 赛事循环定时任务
    public void startCompetitionCircularTask(String param) throws JsonProcessingException {
        if (StringUtils.isBlank(param)) {
            return;
        }
        //反序列化参数
        CompetitionStartSchedulerTaskDTO taskDTO = objectMapper.readValue(param, CompetitionStartSchedulerTaskDTO.class);
        //如果赛事回合次数不存在，则初始化赛事回合次数为1，使用computeIfAbsent方法，保证原子性
        int count = competitionRoughInfoMap.computeIfAbsent(taskDTO.getUnCode(), k -> 1);
        //如果当前轮次大于等于总轮次，则将赛事状态改为结束状态
        if (count >= taskDTO.getRoundCount()) {
            competitionService.updateCompetitionStatus(taskDTO.getCompetitionUnCode(), CompetitionStatusEnum.END_THE_COMP);
            //清空回合数map
            competitionRoughInfoMap.remove(taskDTO.getUnCode());
            //根据赛事unCode查询赛事参赛队伍信息
            List<QueryCompTeamDetailInfoDTO> compTeamDetailInfoList = competitionTeamService.queryCompTeamDetailInfoList(taskDTO.getCompetitionUnCode());
            if (!compTeamDetailInfoList.isEmpty()){
                //获取容器id数组
                String[] containerIdArr = compTeamDetailInfoList.stream().map(QueryCompTeamDetailInfoDTO::getContainerId).toArray(String[]::new);
                //停止容器
                containerService.batchStopContainer(containerIdArr);
                //删除容器
                containerService.batchDeleteContainer(containerIdArr);
            }
            //删除定时任务
            schedulerTaskService.deleteSchedulerTask(taskDTO.getUnCode());
            return;
        }
        //更新赛事回合次数，使用replace方法，保证原子性
        competitionRoughInfoMap.replace(taskDTO.getUnCode(), count + 1);
        //执行赛事回合逻辑
        //更新flag
        dynamicFlagService.batchRefreshFlag(taskDTO.getCompetitionUnCode());
        //更新赛事回合次数
        competitionService.updateCompetitionCurrentRoundCount(taskDTO.getUnCode());
    }
}
